﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OOAD_Project_Editor.Application;
using OOAD_Project_Editor.Foundation;
using OOAD_Project_Engine.Foundation.Interfaces;
using OOAD_Project_Engine.Domain.Factories;
using OOAD_Project_Engine.Domain.Components;
using OOAD_Project_Engine.Foundation.MyEventArgs;
using OOAD_Project_Editor.Domain;

namespace OOAD_Project_Editor.Presentation
{
    public partial class EditorForm : Form
    {
        PreveiwScreen _screen;
        EntityForm _entityForm;
        EntityComponentPropertyForm _propertyForm;
        SceneStructureForm _structureForm;
        readonly float PanelRatio = 800f / 480f;

        public IManageSceneHandler ManageSceneHandler { get { return _screen.ManageSceneHandler; } }
        public ILoadStoreSceneHandler LoadStoreSceneHandler { get { return _screen.LoadStoreSceneHandler; } }

        public EditorForm()
        {
            InitializeComponent();
            this._screen = new PreveiwScreen(DrawingSurface);
            this._entityForm = new EntityForm();
            this._entityForm.OnAddingEntity += this.OnAddingEntity;

            this._propertyForm = new EntityComponentPropertyForm(this);
            _structureForm = new SceneStructureForm(this);

            this._propertyForm.Location = new Point(this.Location.X + this.Width, this.Location.Y + 0);
            this._propertyForm.Show();

            this._entityForm.Location = new Point(this.Location.X, this.Location.Y + this.Height + 0);
            this._entityForm.Show();
            this._entityForm.Visible = false;

            _structureForm.Location = new Point(this.Location.X + this.Width, this.Location.Y + this._propertyForm.Height);
            _structureForm.Show();

            Disposed += new EventHandler(delegate(object sender, EventArgs e)
            {
                if (_screen != null)
                    _screen.Exit();
            });

            ManageSceneHandler.OnFormUpdate += this.OnSceneUpdate;

            ManageSceneHandler.ActionHandler.OnEntitySelectedEvent += this.OnSelectEntity;

            drawingSurfacePanel.Resize += this.onPanelResize;
            updateForm(null);
        }

        void OnSceneUpdate(object sender, SceneUpdateEventArgs e)
        {
            updateForm(e.Scene);
        }

        private void updateForm(IEditableSceneComponent scene)
        {
            if (scene != null)
            {
                _entityForm.Visible = true;
                _propertyForm.Visible = true;
                _structureForm.SetTreeData(scene);
                editToolStripSplitButton.Enabled = true;
                playSceneButton.Enabled = true;
                storeSceneButton.Enabled = true;
                copyToolStripMenuItem.Enabled = ManageSceneHandler.ActionHandler.EnableCopy();
                cutToolStripMenuItem.Enabled = ManageSceneHandler.ActionHandler.EnableCut();
                pasteToolStripMenuItem.Enabled = ManageSceneHandler.ActionHandler.EnablePaste();
            }
            else
            {
                _propertyForm.SetData(null);
                _propertyForm.Visible = false; ;
                _entityForm.Visible = false;
                editToolStripSplitButton.Enabled = false;
                playSceneButton.Enabled = false;
                storeSceneButton.Enabled = false;
            }
        }

        void OnSelectEntity(object sender, SelectEntityEventArgs e)
        {
            IEntity entity = e.Entity;
            _propertyForm.SetData(entity);
        }

        public void AddComponentToEntity(IEntity entity, Type type)
        {
            object[] parameters = new object[0];
            Type spriteType = typeof(Sprite);
            Type tranformType = typeof(Transform);
            if (type == spriteType)
            {
                OpenFileDialog openFileDialog1 = new OpenFileDialog();
                openFileDialog1.InitialDirectory = "c:\\";
                openFileDialog1.Filter = "PNG(*.png)|*.PNG|Jpeg(*.jpg)|*.JPG";
                openFileDialog1.FilterIndex = 1;
                openFileDialog1.RestoreDirectory = true;

                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    string filePath = openFileDialog1.FileName;
                    parameters = new object[] { filePath, false };
                    ManageSceneHandler.AddEntityComponent(entity, type, parameters);
                }
            }
            else if (type == tranformType)
                ManageSceneHandler.AddEntityComponent(entity, type, parameters);
        }

        private void OnAddingEntity(object sender, EntityEventArgs e)
        {
            IEntity entity = e.Entity;
            AsignEntityNameForm form = new AsignEntityNameForm(entity);
            form.OnNameSubmited += this.onEntityNameSubmited;
            form.Show();
        }

        private void onEntityNameSubmited(object sender, EntityEventArgs e)
        {
            AddEntityToScene(e.Name, e.Entity);
        }

        private void AddEntityToScene(String name, IEntity entityPrototype)
        {
            if (ManageSceneHandler.CurrentScene.AllEntitys.ContainsKey(name))
            {
                MessageBox.Show("a Entity names\' " + name + " \'is already exists!\nplaese set another name!");
            }
            else
                ManageSceneHandler.DuplicateEntity(name, entityPrototype);
        }

        private void OnEntityComponentSelected(object sender, CustomEventArgs<Type> e)
        {
            if (sender is EntityComponentForm)
            {
                EntityComponentForm ec = sender as EntityComponentForm;
                IEntity entity = ec.Entity;
                AddComponentToEntity(entity, e.Value);
            }
        }

        public void AddEntityComponent(IEntity entity)
        {
            EntityComponentForm componentForm = new EntityComponentForm(entity);
            componentForm.Location = new Point(this.Location.X + _entityForm.Width, this.Location.Y + this.Height);
            componentForm.OnEntityComponentSelected += this.OnEntityComponentSelected;
            componentForm.Show();
        }

        public void RemoveEntity(IEntity entity)
        {
            ManageSceneHandler.RemoveEntity(entity);
        }

        public void RemoveEntityComponent(IEntityComponent component)
        {
            ManageSceneHandler.RemoveEntityComponent(component.Owner, component);
        }

        #region UI

        public void Run()
        {
            _screen.Run();
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x0112) // WM_SYSCOMMAND
            {
                // Check your window state here
                if (m.WParam == new IntPtr(0xF030)) // Maximize event - SC_MAXIMIZE from Winuser.h
                {
                    _entityForm.TopMost = true;
                    _propertyForm.TopMost = true;
                    _structureForm.TopMost = true;
                }
                else// if (m.WParam == new IntPtr(0xF120)) // Restore event - SC_RESTORE  from Winuser.h
                {
                    _entityForm.TopMost = false;
                    _propertyForm.TopMost = false;
                    _structureForm.TopMost = false;
                }
            }
            base.WndProc(ref m);
        }

        void onPanelResize(object sender, EventArgs e)
        {
            Panel p = sender as Panel;

            int w = p.Size.Width;
            int h = p.Size.Height;

            float tempR = (float)w / (float)h;

            if (tempR > PanelRatio)//較原畫面扁 以高做基準
            {
                p.Width = (int)(p.Size.Height * PanelRatio);
            }
            else//較原畫面窄 以寬做基準
            {
                p.Height = (int)(p.Size.Width / PanelRatio);
            }
        }

        public IntPtr DrawingSurface
        {
            get
            {
                return drawingSurfacePanel.Handle;
            }
        }

        private void newSceneButton_Click(object sender, EventArgs e)
        {
            drawingSurfacePanel.Enabled = true;
            ManageSceneHandler.CreateEmptyScene();
        }

        private void loadFileButton_Click(object sender, EventArgs e)
        {
            drawingSurfacePanel.Enabled = true;
            ManageSceneHandler.SetManageScene(LoadStoreSceneHandler.Load());
        }

        private void storeFileButton_Click(object sender, EventArgs e)
        {
            bool cancel = false;
            IEditableSceneComponent scene = ManageSceneHandler.CurrentScene;
            string result = "";
            if (scene != null)
            {

                if (this.LoadStoreSceneHandler.Store(scene.ToScript()))
                    result = "scene saved!!";
                else
                    cancel = true;
            }
            else
                result = "Null Scene!!";
            if (!cancel)
                MessageBox.Show(result);
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ManageSceneHandler.CopyEntity();
        }

        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ManageSceneHandler.CutEntity();
        }

        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ManageSceneHandler.PasteEntity();
        }

        private void drawingSurfacePanel_MouseMove(object sender, MouseEventArgs e)
        {
            ManageSceneHandler.OnMouseMove();
        }

        private void drawingSurfacePanel_MouseUp(object sender, MouseEventArgs e)
        {
            ManageSceneHandler.OnMouseUp();
        }

        private void drawingSurfacePanel_MouseDown(object sender, MouseEventArgs e)
        {
            ManageSceneHandler.OnMouseDown();
        }

        #endregion





    }
}
